package com.lebang.service.cences;

import com.lebang.domain.CencesAdRecordLog;
import com.lebang.domain.CencesReqAdCount;
import com.lebang.domain.CencesSdkAdCount;
import com.lebang.example.CencesAdRecordLogExample;
import com.lebang.mapper.*;
import com.lebang.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
* 
* @Author ljx
* @Date 2020-12-08
*/
@Service
public class CencesAdRecordLogService extends BaseService<CencesAdRecordLog,Integer, CencesAdRecordLogExample>{
    @Autowired
    private TaskRouseMapper taskRouseMapper;
    @Autowired
    private AdRecordLogMapper adRecordLogMapper;
    @Autowired
    private CencesAdRecordLogMapper mapper;
    @Autowired
    private CencesReqAdCountMapper cencesReqAdCountMapper;
    @Autowired
    private CencesSdkAdCountMapper cencesSdkAdCountMapper;


    /**
     * 广告填充统计
     * @param end
     * @param value
     */
    public void starDataInit(LocalDateTime end,Integer value) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDateTime star = end.minusDays(1);

        //统计日期
        int time = Integer.parseInt(end.toLocalDate().minusDays(1).format(df));

        List<String> sdkKey = taskRouseMapper.selectAllKey();

        //请求数
        List<CencesAdRecordLog> count=adRecordLogMapper.countByTime(star,end);
        Map<String, List<CencesAdRecordLog>> countMap = count.stream().collect(Collectors.groupingBy(CencesAdRecordLog::getSdkKey));


        //成功数
        List<CencesAdRecordLog> successCount=adRecordLogMapper.countSuccessByTime(star,end);
        Map<String, List<CencesAdRecordLog>> successCountMap = successCount.stream().collect(Collectors.groupingBy(CencesAdRecordLog::getSdkKey));

        //失败数
        List<CencesAdRecordLog> failCount=adRecordLogMapper.countFailByTime(star,end);
        Map<String, List<CencesAdRecordLog>> failCountMap = failCount.stream().collect(Collectors.groupingBy(CencesAdRecordLog::getSdkKey));

        //成功展示数
        List<CencesAdRecordLog> successShowCount=adRecordLogMapper.countSuccessShowByTime(star,end);
        Map<String, List<CencesAdRecordLog>> successShowCountMap = successShowCount.stream().collect(Collectors.groupingBy(CencesAdRecordLog::getSdkKey));

        //填充率=成功/(成功+失败)

        //展示率=成功展示/成功数

        //过滤下载数
        List<CencesAdRecordLog> filterDownloadCount=adRecordLogMapper.countFilterDownloadByTime(star,end);
        Map<String, List<CencesAdRecordLog>> filterDownloadCountMap = filterDownloadCount.stream().collect(Collectors.groupingBy(CencesAdRecordLog::getSdkKey));

        //过滤浏览数
        List<CencesAdRecordLog> filterBrowseCount=adRecordLogMapper.countFilterBrowseByTime(star,end);
        Map<String, List<CencesAdRecordLog>> filterBrowseCountMap = filterBrowseCount.stream().collect(Collectors.groupingBy(CencesAdRecordLog::getSdkKey));

        //过滤率=(过滤下载+过滤浏览)/成功数

        AtomicInteger allCount = new AtomicInteger(0);
        AtomicInteger allSuccessCount = new AtomicInteger(0);
        AtomicInteger allFailCount = new AtomicInteger(0);
        AtomicInteger allSuccessShowCount = new AtomicInteger(0);
        AtomicInteger allFilterDownloadCount = new AtomicInteger(0);
        AtomicInteger allFilterBrowseCount = new AtomicInteger(0);

        //分数据源
        for (String key : sdkKey) {
            BigDecimal keySuccessCount = new BigDecimal(this.getSuccessCount(successCountMap,key));
            BigDecimal keyFailCount = new BigDecimal(this.getFailCount(failCountMap,key));
            BigDecimal keySuccessShowCount = new BigDecimal(this.getSuccessShowCount(successShowCountMap,key));
            BigDecimal keyFilterDownloadCount = new BigDecimal(this.getFilterDownloadCount(filterDownloadCountMap,key));
            BigDecimal keyFilterBrowseCount = new BigDecimal(this.getFilterBrowseCount(filterBrowseCountMap,key));

            CencesAdRecordLog cencesAdRecordLog=new CencesAdRecordLog();
            cencesAdRecordLog.setCreateTime(LocalDateTime.now());
            cencesAdRecordLog.setTime(time);
            cencesAdRecordLog.setCount(this.getCount(countMap,key));
            cencesAdRecordLog.setSuccessCount(keySuccessCount.intValue());
            cencesAdRecordLog.setFailCount(keyFailCount.intValue());
            cencesAdRecordLog.setSuccessShowCount(keySuccessShowCount.intValue());
            if ((keyFailCount.add(keySuccessCount)).intValue()  != 0){
                cencesAdRecordLog.setFillingRate(keySuccessCount.divide(keyFailCount.add(keySuccessCount),2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
            }else {
                cencesAdRecordLog.setFillingRate(0);
            }
            if (keySuccessCount.intValue() != 0){
                cencesAdRecordLog.setShowRate(keySuccessShowCount.divide(keySuccessCount,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
            }else {
                cencesAdRecordLog.setShowRate(0);
            }
            cencesAdRecordLog.setSdkKey(key);
            cencesAdRecordLog.setFilterDownloadCount(keyFilterDownloadCount.intValue());
            cencesAdRecordLog.setFilterBrowseCount(keyFilterBrowseCount.intValue());
            BigDecimal sum=new BigDecimal(keyFilterDownloadCount.intValue()+keyFilterBrowseCount.intValue());
            if (keySuccessCount.intValue() != 0){
                cencesAdRecordLog.setFilterRate(sum.divide(keySuccessCount,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
            }else {
                cencesAdRecordLog.setFilterRate(0);
            }
            mapper.insertSelective(cencesAdRecordLog);
            allCount.addAndGet(cencesAdRecordLog.getCount());
            allSuccessCount.addAndGet(cencesAdRecordLog.getSuccessCount());
            allFailCount.addAndGet(cencesAdRecordLog.getFailCount());
            allSuccessShowCount.addAndGet(cencesAdRecordLog.getSuccessShowCount());
            allFilterDownloadCount.addAndGet(cencesAdRecordLog.getFilterDownloadCount());
            allFilterBrowseCount.addAndGet(cencesAdRecordLog.getFilterBrowseCount());
        }

        //所有数据源
        BigDecimal allKeySuccessCount = new BigDecimal(allSuccessCount.get());
        BigDecimal allKeyFailCount = new BigDecimal(allFailCount.get());
        BigDecimal allKeySuccessShowCount = new BigDecimal(allSuccessShowCount.get());

        CencesAdRecordLog cencesAdRecordLog=new CencesAdRecordLog();
        cencesAdRecordLog.setCreateTime(LocalDateTime.now());
        cencesAdRecordLog.setTime(time);
        cencesAdRecordLog.setCount(allCount.get());
        cencesAdRecordLog.setSuccessCount(allKeySuccessCount.intValue());
        cencesAdRecordLog.setFailCount(allKeyFailCount.intValue());
        cencesAdRecordLog.setSuccessShowCount(allKeySuccessShowCount.intValue());
        if ((allKeyFailCount.add(allKeySuccessCount).intValue()) != 0){
            cencesAdRecordLog.setFillingRate(allKeySuccessCount.divide(allKeyFailCount.add(allKeySuccessCount),2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
        }else {
            cencesAdRecordLog.setFillingRate(0);
        }
        if (allKeySuccessCount.intValue() != 0){
            cencesAdRecordLog.setShowRate(allKeySuccessShowCount.divide(allKeySuccessCount,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
        }else {
            cencesAdRecordLog.setShowRate(0);
        }
        cencesAdRecordLog.setFilterDownloadCount(allFilterDownloadCount.get());
        cencesAdRecordLog.setFilterBrowseCount(allFilterBrowseCount.get());
        BigDecimal sum=new BigDecimal(allFilterDownloadCount.get()+allFilterBrowseCount.get());
        if (allKeySuccessCount.intValue() != 0){
            cencesAdRecordLog.setFilterRate(sum.divide(allKeySuccessCount,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
        }else {
            cencesAdRecordLog.setFilterRate(0);
        }
        cencesAdRecordLog.setSdkKey("all");
        mapper.insertSelective(cencesAdRecordLog);

        //统计请求成功数超过最大值用户
        if (value !=null){
            List<CencesReqAdCount> cencesReqAdCounts = cencesReqAdCountMapper.selectReqAdCount(value,star,end);
            for (CencesReqAdCount cencesReqAdCount : cencesReqAdCounts) {
                cencesReqAdCount.setCreateTime(LocalDateTime.now());
                cencesReqAdCount.setModifyTime(LocalDateTime.now());
                cencesReqAdCount.setStatus(0);
                cencesReqAdCountMapper.insertSelective(cencesReqAdCount);
            }

            List<CencesReqAdCount> reqAdCounts=new ArrayList<>();
            cencesReqAdCounts.parallelStream().collect(Collectors.groupingBy(o -> (o.getMemberId() + o.getSdkKey()), Collectors.toList())).forEach(
                    (id, transfer) -> {
                        transfer.stream().reduce((a,b)->new CencesReqAdCount(a.getMemberId(),a.getSdkKey(),a.getReqCount()+b.getReqCount())).ifPresent(reqAdCounts::add);
                    }
            );
            for (CencesReqAdCount reqAdCount : reqAdCounts) {
                CencesSdkAdCount cencesSdkAdCount=new CencesSdkAdCount();
                cencesSdkAdCount.setCreateTime(LocalDateTime.now());
                cencesSdkAdCount.setModifyTime(LocalDateTime.now());
                cencesSdkAdCount.setReqCount(reqAdCount.getReqCount());
                cencesSdkAdCount.setMemberId(reqAdCount.getMemberId());
                cencesSdkAdCount.setSdkKey(reqAdCount.getSdkKey());
                cencesSdkAdCount.setStatus(0);
                cencesSdkAdCountMapper.insertSelective(cencesSdkAdCount);
            }
        }

    }

    private Integer getFilterBrowseCount(Map<String, List<CencesAdRecordLog>> map, String key) {
        AtomicInteger finish = new AtomicInteger(0);
        List<CencesAdRecordLog> cencesBusMembers = map.get(key);
        if (cencesBusMembers == null) {
            return finish.get();
        }
        cencesBusMembers.forEach(s -> {
            finish.addAndGet(s.getFilterBrowseCount());
        });
        return finish.get();
    }

    /**
     * 过滤下载数
     * @param map
     * @param key
     * @return
     */
    private Integer getFilterDownloadCount(Map<String, List<CencesAdRecordLog>> map, String key) {
        AtomicInteger finish = new AtomicInteger(0);
        List<CencesAdRecordLog> cencesBusMembers = map.get(key);
        if (cencesBusMembers == null) {
            return finish.get();
        }
        cencesBusMembers.forEach(s -> {
            finish.addAndGet(s.getFilterDownloadCount());
        });
        return finish.get();
    }

    /**
     * 请求数
     * @param map
     * @param key
     * @return
     */
    private Integer getCount( Map<String, List<CencesAdRecordLog>> map, String key) {
        AtomicInteger finish = new AtomicInteger(0);
        List<CencesAdRecordLog> cencesBusMembers = map.get(key);
        if (cencesBusMembers == null) {
            return finish.get();
        }
        cencesBusMembers.forEach(s -> {
            finish.addAndGet(s.getCount());
        });
        return finish.get();
    }

    /**
     * 成功数
     * @param map
     * @param key
     * @return
     */
    private Integer getSuccessCount( Map<String, List<CencesAdRecordLog>> map, String key) {
        AtomicInteger finish = new AtomicInteger(0);
        List<CencesAdRecordLog> cencesBusMembers = map.get(key);
        if (cencesBusMembers == null) {
            return finish.get();
        }
        cencesBusMembers.forEach(s -> {
            finish.addAndGet(s.getSuccessCount());
        });
        return finish.get();
    }

    /**
     * 失败数
     * @param map
     * @param key
     * @return
     */
    private Integer getFailCount( Map<String, List<CencesAdRecordLog>> map, String key) {
        AtomicInteger finish = new AtomicInteger(0);
        List<CencesAdRecordLog> cencesBusMembers = map.get(key);
        if (cencesBusMembers == null) {
            return finish.get();
        }
        cencesBusMembers.forEach(s -> {
            finish.addAndGet(s.getFailCount());
        });
        return finish.get();
    }

    /**
     * 成功展示数
     * @param map
     * @param key
     * @return
     */
    private Integer getSuccessShowCount( Map<String, List<CencesAdRecordLog>> map, String key) {
        AtomicInteger finish = new AtomicInteger(0);
        List<CencesAdRecordLog> cencesBusMembers = map.get(key);
        if (cencesBusMembers == null) {
            return finish.get();
        }
        cencesBusMembers.forEach(s -> {
            finish.addAndGet(s.getSuccessShowCount());
        });
        return finish.get();
    }

    public Integer deleteByTime(Integer time) {
        return mapper.deleteByTime(time);
    }
}
